package source.Control 
{
	import flash.utils.ByteArray;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import net.flashpunk.FP;
	import net.flashpunk.Entity;
	import net.flashpunk.graphics.Image;
	import net.flashpunk.graphics.Tilemap;
	
	import source.Assets;
	import source.Global;
	import source.Objetos.*;
	import source.Solidos.*;

	
	public class Pantalla 
	{
		
		private var world:Juego;
		public var tilesetPrincipal:Tilemap;
		public var tilesetAuxiliar:Tilemap;
		public var tilesetFondo:Tilemap;
		
		public function Pantalla(world:Juego) 
		{
			this.world = world;
		}
		

		
		/**
         * siguientePantalla
		 * Configura la siguiente pantalla (elimina todas las entidades del mundo actual) para ser cargada más adelante.
		 */
		public function siguientePantalla():void {
			Global.pjTemp = Global.pj; //guardamos el estado actual del pj antes del removeAll(), se utilizará en el método restaurarPJ()
			world.removeAll();
			
			if (Global.salirPantalla_porPuerta) {
				Global.idPantallaActual = Global.pantallaDestino;
				cargarPantalla();
				Global.salirPantalla_porPuerta = false;
			}
			
			else if (Global.salirPantalla_porTeletransporte) {
				Global.idPantallaActual = Global.pantallaDestino;
				cargarPantalla();
				Global.salirPantalla_porTeletransporte = false;
			}
			
			else if (Global.salirPantalla_porBorde) {
				switch (Global.salirPantalla_porBorde_Lado) {
					case "n":
						Global.idPantallaActual = int(Global.pantallaN);
						Global.pjTemp.y = FP.height - Global.pj.height + Global.pj.originY; //la propiedad originY va sumando porque es negativa
						break;
					case "e":
						Global.idPantallaActual = int(Global.pantallaE);
						Global.pjTemp.x = 0;
						break;
					case "s":
						Global.idPantallaActual = int(Global.pantallaS);
						Global.pjTemp.y = 0;
						break;
					case "o":
						Global.idPantallaActual = int(Global.pantallaO);
						Global.pjTemp.x = FP.width - Global.pj.width + Global.pj.originX; //la propiedad originX va sumando porque es negativa
						break;
				}
				
				cargarPantalla();
				Global.salirPantalla_porBorde = false;
			}
			
			else if (Global.respawn) {
				Global.idPantallaActual = Global.savepointDestino; //Global.savepoint_destino es la id de la pantalla del savepoint donde se guardó la última vez
				cargarPantalla();
				Global.respawn = false;
			}
		}
		
		
		/**
         * cargarPantalla
		 * Carga la siguiente pantalla.
		 */
		public function cargarPantalla():void {
			//cargamos el XML:
			var file:ByteArray = new Assets.PANTALLAS[Global.idPantallaActual];
			var str:String = file.readUTFBytes(file.length); //con este objeto echamos un vistazo "por encima" sobre ciertas partes, simplemente como un texto
			var xml:XML = new XML(str);                      //con este objeto buscamos datos específicos, ya entendiendo el formato XML
			
			//declaramos estos objetos que contendrán información sobre los elementos del fichero XML:
			var o:XML, p:XML;
			
			//configuramos el tamaño de la pantalla:
			FP.width = Global.resAncho;
			FP.height = Global.resAlto;
            
            //Realizamos una comprobación sobre la ID de la pantalla:
			if (Global.idPantallaActual != xml.@id) FP.console.log("ID de pantalla incorrecta.")
            
            //añadimos el fondo:
            if (xml.@fondo != "singrafico")
                world.add(new Entity(0, 0, new Image(Assets[xml.@fondo])));
			
			//añadimos los solidos:
			if(str.search("<solido") > 0)
				for each (o in xml.solido[0].rect)
					world.add(new Solid(o.@x, o.@y, o.@w, o.@h));
					
			//añadimos el agua:
			if(str.search("<agua") > 0)
				for each (o in xml.agua[0].rect)
					world.add(new Agua(o.@x, o.@y, o.@w, o.@h));
			
			//añadimos los tiles de muerte:
			if(str.search("<muerte") > 0)
				for each (o in xml.muerte[0].rect)
					world.add(new Muerte(o.@x, o.@y, o.@w, o.@h));
                    
            //añadimos los tiles del tileset de fondo:
            var indice:uint = uint(String(xml.tilesFondo[0].@tileset).substring(7, 8));
            world.add(new Entity(0, 0, tilesetFondo = new Tilemap(Assets.TILESETS[indice], FP.width, FP.height, Global.grid, Global.grid)));
            for each (o in xml.tilesFondo[0].tile)
                tilesetFondo.setTile(o.@x, o.@y, o.@id);
			
			//añadimos los objetos que van detrás del pj:
			if(str.search("<objetos") > 0) {
				for each (o in xml.objetos[0].savepoint) 	  world.add(new Savepoint(o.@x, o.@y, Global.idPantallaActual));                            //savepoints
				for each (o in xml.objetos[0].puerta_ext) 	  world.add(new Puerta(o.@x, o.@y, false, o.@pantalla_destino));                            //puertas exteriores
				for each (o in xml.objetos[0].teletransporte) world.add(new Teletransporte(o.@x, o.@y, o.@pant_dest, new Point(o.@dest_x, o.@dest_y))); //teletransportes
				for each (o in xml.objetos[0].cartel) 		  world.add(new Cartel(o.@x, o.@y, o.@texto));                                              //carteles
			}
            
			//añadimos los detalles que van detrás del pj y los npcs:
			if (str.search("<detalles") > 0) {
				var detallesXML:XMLList = xml.detalles.child("*");
				
				for each (o in detallesXML)
				//trace(String(o));
					if (o.@delante == "False")
						world.add(new Detalle(o.@x, o.@y, String(o.name().localName), o.@nSprites));
			}
            
            //añadimos los npcs:
            if(str.search("<objetos") > 0) {
				for each (o in xml.objetos[0].npc) {
                    var _listaNodos:Array = new Array();
                    //Primero introducimos la posición inicial del NPC:
                    _listaNodos.push(new Point(o.@x, o.@y));
                    //Posteriormente llenamos un buffer con todos los nodos:
                    for each (p in o.node)
                        _listaNodos.push(new Point(p.@x, p.@y));
                    //Finalmente creamos y agregamos el NPC al mundo:
                    world.add(new NPC(o.@x, o.@y, o.@dialogo, o.@grafico, _listaNodos, Number(String(o.@velocidad).replace(",", "."))));
                }
            }
            
            //añadimos los enemigos:
            if(str.search("<objetos") > 0) {
				for each (o in xml.objetos[0].enemigo) {
                    _listaNodos = new Array();
                    //Primero introducimos la posición inicial del enemigo:
                    _listaNodos.push(new Point(o.@x, o.@y));
                    //Posteriormente llenamos un buffer con todos los nodos:
                    for each (p in o.node)
                        _listaNodos.push(new Point(p.@x, p.@y));
                    //Finalmente creamos y agregamos el enemigo al mundo:
                    world.add(new Enemigo(o.@x, o.@y,
                                          o.@grafico,
                                          o.@muerte_al_contacto,
                                          _listaNodos, Number(String(o.@velocidad).replace(",", ".")),
                                          o.@copiasaltos,
                                          o.@ddireccA,
                                          o.@ddireccB,
                                          o.@ddireccC,
                                          o.@flotante));
                }
            }
			
			//añadimos el pj (tras añadir el pj, lo demás se verá "delante" de él, y lo ya añadido se verá "detrás"):
			if (Global.salirPantalla_porBorde) { //si estamos cargando la pantalla debido a que hemos salido por un borde...
				world.add(Global.pj = new PJ(Global.pjTemp.x, Global.pjTemp.y));
				world.restaurarPJ(); //restauramos las propiedades que el PJ tenía al salir de la pantalla anterior
			}
			else if (Global.salirPantalla_porTeletransporte || Global.salirPantalla_porPuerta) { //si estamos cargando la pantalla debido a que hemos salido por un teletransporte...)
				world.add(Global.pj = new PJ(Global.tileDestino.x * Global.grid + Global.pj.originX/2, //Global.pj.originX es un número negativo que expresa
									   Global.tileDestino.y * Global.grid));					 //el centro relativo (para rotaciones, por ejemplo)
				world.restaurarPJ(); //restauramos las propiedades que el PJ tenía al salir de la pantalla anterior
			}
			else if (Global.respawn) { //si estamos cargando la pantalla debido a que debemos resucitar o hemos cargado la partida..
				for each (o in xml.objetos[0].savepoint)
					world.add(Global.pj = new PJ(uint(o.@x) + Global.grid/2 - Global.anchoSpritePJ/2,
                                           uint(o.@y)));
				world.restaurarPJ(); //restauramos las propiedades que el PJ tenía antes de morir o cuando se guardó la partida
			}
			else { //si estamos cargando la pantalla debido a que acabamos de comenzar el juego...
				world.add(Global.pj = new PJ(uint(xml.objetos[0].start.@x) + Global.grid/2 - Global.anchoSpritePJ/2,
                                       xml.objetos[0].start.@y));
				Global.savepointDestino = Global.idPantallaActual;
			}
			
			//añadimos los objetos que van delante del pj:
			if(str.search("<objetos") > 0) {
				for each (o in xml.objetos[0].bloque)               world.add(new Bloque(o.@x, o.@y));        //bloques
				for each (o in xml.objetos[0].plataforma_unidirecc)	world.add(new PlatUnidirecc(o.@x, o.@y)); //plataformas unidireccionales
				for each (o in xml.objetos[0].caja)                 world.add(new Caja(o.@x, o.@y));          //cajas
				for each (o in xml.objetos[0].puas_n)               world.add(new Puas(o.@x, o.@y, "n"));     //puas desde arriba
				for each (o in xml.objetos[0].puas_e)               world.add(new Puas(o.@x, o.@y, "e"));     //puas desde la derecha
				for each (o in xml.objetos[0].puas_s)               world.add(new Puas(o.@x, o.@y, "s"));     //puas desde abajo
				for each (o in xml.objetos[0].puas_o)               world.add(new Puas(o.@x, o.@y, "o"));     //puas desde la izquierda
				for each (o in xml.objetos[0].pinchos)              world.add(new Pinchos(o.@x, o.@y));       //pinchos
				for each (o in xml.objetos[0].plataforma_movil)     world.add(new PlatMovil(o.@x, o.@y, o.@direccion_vertical, o.@sentido_positivo, o.@velocidad)); //plataformas móviles
				for each (o in xml.objetos[0].puerta_int)           world.add(new Puerta(o.@x, o.@y, true, o.@pantalla_destino)); 	                              //puertas interiores
				for each (o in xml.objetos[0].powerup)              world.add(new Powerup(o.@x, o.@y, new Array(o.@correr,                                          //powerups
																									  o.@doble_salto,
																									  o.@disparar,
																									  o.@nadar,
																									  o.@empujar,
																									  o.@golpe_descendente)));
			}
			
			//añadimos los tiles del tileset principal al world:
			indice = uint(String(xml.tiles[0].@tileset).substring(7, 8));
			world.add(new Entity(0, 0, tilesetPrincipal = new Tilemap(Assets.TILESETS[indice], FP.width, FP.height, Global.grid, Global.grid)));
            for each (o in xml.tiles[0].tile)
                tilesetPrincipal.setTile(o.@x, o.@y, o.@id);
			
            //añadimos los tiles del tileset auxiliar:
            indice = uint(String(xml.tilesAux[0].@tileset).substring(7, 8));
            world.add(new Entity(0, 0, tilesetAuxiliar = new Tilemap(Assets.TILESETS[indice], FP.width, FP.height, Global.grid, Global.grid)));
            for each (o in xml.tilesAux[0].tile)
                tilesetAuxiliar.setTile(o.@x, o.@y, o.@id);
			
			//añadimos los detalles que van delante del pj:
			if (str.search("<detalles") > 0) {	
				detallesXML = xml.detalles.child("*");
				for each (o in detallesXML)
					if (o.@delante == "True")
						world.add(new Detalle(o.@x, o.@y, String(o.name().localName), o.@nSprites));
			}		
				
			//almacenamos la información de conexiones de esta pantalla con otras:
			Global.pantallaN = int(xml.@conex_n);
			Global.pantallaE = int(xml.@conex_e);
			Global.pantallaS = int(xml.@conex_s);
			Global.pantallaO = int(xml.@conex_o);
			
			//almacenamos la ID de la pantalla y la mostramos por la consola del FlashPunk:
			FP.console.log("Pantalla actual: " + Global.idPantallaActual);
			
			//set the view to follow the player, within no restraints, and let it "stray" from the player a bit.
			//for example, if the last parameter was 1, the view would be static with the player. If it was 10, then
			//it would trail behind the player a bit. Higher the number, slower it follows.
			world.add(Global.vista = new Vista(Global.pj as Entity, new Rectangle(0, 0, FP.width,FP.height), 10));
		}
		
		
	}

}